package ua.amsoft.brelok.preference;

import java.io.IOException;
import java.util.Date;

import org.apache.http.client.ClientProtocolException;

import ua.amsoft.brelok.R;
import ua.amsoft.brelok.constant.Constants;
import ua.amsoft.brelok.filter.EditTextMinMaxValueInputFilter;
import ua.amsoft.brelok.manager.AuthenticationManager;
import ua.amsoft.brelok.manager.ConnectionManager;
import ua.amsoft.brelok.manager.PreferencesManager;
import ua.amsoft.brelok.manager.WidgetUpdateManager;
import ua.amsoft.brelok.service.UpdateService;
import ua.amsoft.brelok.util.DateTimeUtils;
import ua.amsoft.brelok.widget.UpdateStartReceiver;
import ua.amsoft.brelok.widget.UpdateStopReceiver;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.telephony.TelephonyManager;
import android.text.InputFilter;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

/**
 * @author Tair Mustafaiev
 */
public class BrelokPreferenceActivity extends PreferenceActivity {
    
    private static final long INTERVAL_DAY = 86400000L;
    
    private static final String AUTH_FAILED_MESSAGE = "Authentication was not passed for URL: %s and IMEI: %s";
    
    private static final String AUTHE_SUCCESS_MESSAGE = "Authentication passed for URL: %s and IMEI: %s";
    
    private static final String TAG = BrelokPreferenceActivity.class.getName();
    
    private int widgetId;
    
    /**
     * "Done" button on click listener
     */
    private final View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(final View v) {
            final Context context = BrelokPreferenceActivity.this;
            final ConnectionManager manager = new ConnectionManager();
            if (!manager.isNetworkConnected(context)) {
                Toast.makeText(context, context.getString(R.string.error_network_disconnected),
                        Toast.LENGTH_SHORT).show();
                Log.i(BrelokPreferenceActivity.TAG, "Network is disconnected");
            } else {
                processClick(context);
            }
        }
        
        /**
         * Processes Done button click
         * 
         * @param context
         */
        private void processClick(final Context context) {
            // When the button is clicked, save the string in prefs and
            // return that they clicked Done.
            final String urlValue = getSharedPreferences().getString("url", "http://google.com");
            Log.d("entered url", urlValue);
            final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            final String imei = telephonyManager.getDeviceId();
            final AuthenticationManager authenticationManager = new AuthenticationManager();
            
            try {
                resolveClickAction(context, urlValue, imei, authenticationManager);
            } catch (final ClientProtocolException e) {
                Log.e(BrelokPreferenceActivity.TAG, e.getLocalizedMessage());
            } catch (final IOException e) {
                Log.e(BrelokPreferenceActivity.TAG, e.getLocalizedMessage());
            }
        }
        
        /**
         * Resolves the flow after preferences was confirmed
         * 
         * @param context - {@link Context}
         * @param urlValue - url
         * @param imei - phone's IMEI
         * @param authenticationManager - Auth manager
         * @throws ClientProtocolException - will be thrown
         * @throws IOException - will be thrown
         */
        private void resolveClickAction(final Context context, final String urlValue,
                final String imei, final AuthenticationManager authenticationManager)
                throws ClientProtocolException, IOException {
            if (!authenticationManager.checkAuthentication(urlValue, imei)) {
                setResult(Activity.RESULT_CANCELED);
                Toast.makeText(context, context.getString(R.string.error_auth_failed),
                        Toast.LENGTH_LONG).show();
                Log.i(BrelokPreferenceActivity.TAG,
                        String.format(BrelokPreferenceActivity.AUTH_FAILED_MESSAGE, urlValue, imei));
            } else {
                finishActivity(context);
                startUpdateService(context);
                Log.i(BrelokPreferenceActivity.TAG, String.format(
                        BrelokPreferenceActivity.AUTHE_SUCCESS_MESSAGE, urlValue, imei));
            }
        }
        
        /**
         * Finishes configuration activity and puts extra values
         * 
         * @param context
         */
        private void finishActivity(final Context context) {
            // Push widget update to surface with newly set prefix
            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
            WidgetUpdateManager.updateAppWidget(context, appWidgetManager,
                    BrelokPreferenceActivity.this.widgetId);
            // Make sure we pass back the original widgetId
            final Intent resultValue = new Intent();
            resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    BrelokPreferenceActivity.this.widgetId);
            setResult(Activity.RESULT_OK, resultValue);
            finish();
            Log.i(BrelokPreferenceActivity.TAG, "Configuration activity finished");
        }
    };
    
    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        Log.i(BrelokPreferenceActivity.TAG, "Started creation of preferences activity");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_preferences);
        // setResult(Activity.RESULT_CANCELED);
        this.widgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
        // deprecated methods are used for supporting min API Level 11
        addPreferencesFromResource(R.xml.preferences);
        setEditTextFieldFilters();
        setWidgetId();
        findViewById(R.id.done_button).setOnClickListener(this.clickListener);
        Log.i(BrelokPreferenceActivity.TAG, "PreferencesActivity creation finished");
    }
    
    /**
     * Returns {@link SharedPreferences} object
     * 
     * @return {@link SharedPreferences}
     */
    public SharedPreferences getSharedPreferences() {
        return PreferenceManager.getDefaultSharedPreferences(this);
    }
    
    /**
     * Initializes {@link EditText} filters
     */
    private void setEditTextFieldFilters() {
        final EditTextPreference pref = (EditTextPreference) findPreference("days_before_notify");
        final EditTextPreference chartMonthsCount = (EditTextPreference) findPreference("chart_months_count");
        final EditTextPreference passwordExpiryPeriod = (EditTextPreference) findPreference("brelok_user_password_expiration_period");
        passwordExpiryPeriod.getEditText().setFilters(
                new InputFilter[] { new EditTextMinMaxValueInputFilter(1, 999) });
        chartMonthsCount.getEditText().setFilters(
                new InputFilter[] { new EditTextMinMaxValueInputFilter(1, 12) });
        pref.getEditText().setFilters(
                new InputFilter[] { new EditTextMinMaxValueInputFilter(1, 999) });
    }
    
    /**
     * Sets widget ID
     */
    private void setWidgetId() {
        this.widgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
        final Intent intent = getIntent();
        final Bundle extras = intent.getExtras();
        if (extras != null) {
            this.widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
        }
        if (this.widgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
            finish();
        }
    }
    
    /**
     * Starts widget update service
     * 
     * @param context - {@link Context}
     */
    private void startUpdateService(final Context context) {
        final Intent intent = new Intent(context, UpdateService.class);
        context.startService(intent);
        initSchedulers();
        Log.i(BrelokPreferenceActivity.TAG, "Update service is started");
    }
    
    /**
     * Initializes updates scheduler by user setted preferences
     */
    private void initSchedulers() {
        Log.i(BrelokPreferenceActivity.TAG, "Schedulers initialization started");
        final PreferencesManager preferencesManager = new PreferencesManager();
        sendStartUpdatePendingIntent(preferencesManager);
        sendStopUpdatePendingIntent(preferencesManager);
        Log.i(BrelokPreferenceActivity.TAG, "Schedulers initialization finished");
    }
    
    /**
     * Starts {@link UpdateStartReceiver} broadcast receiver
     * 
     * @param preferencesManager - {@link PreferenceManager}
     */
    private void sendStartUpdatePendingIntent(final PreferencesManager preferencesManager) {
        final Intent updateStartIntent = new Intent(getApplicationContext(),
                UpdateStartReceiver.class);
        updateStartIntent.setAction(UpdateStartReceiver.START_RECEIVER_ACTION);
        final AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(
                Context.ALARM_SERVICE);
        final String timeFrom = preferencesManager.getPrefByName(getApplicationContext(),
                Constants.PREF_UPDATING_TIME_FROM, "08:00");
        final String timeTill = preferencesManager.getPrefByName(getApplicationContext(),
                Constants.PREF_UPDATING_TIME_TILL, "20:00");
        final Date updateFrom = DateTimeUtils.calculateBeginingOfDay(timeFrom, timeTill);
        final PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0,
                updateStartIntent, 0);
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateFrom.getTime(),
                BrelokPreferenceActivity.INTERVAL_DAY, pendingIntent);
        Log.i(BrelokPreferenceActivity.TAG,
                "Setted AlarmManager for UpdateStartReceiver which will started at "
                        + updateFrom.toString());
    }
    
    /**
     * Starts {@link UpdateStopReceiver} broadcast receiver
     * 
     * @param preferencesManager - {@link PreferenceManager}
     */
    private void sendStopUpdatePendingIntent(final PreferencesManager preferencesManager) {
        final Intent updateStopIntent = new Intent(getApplicationContext(),
                UpdateStopReceiver.class);
        updateStopIntent.setAction(UpdateStopReceiver.STOP_RECEIVER_ACTION);
        final AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(
                Context.ALARM_SERVICE);
        final String timeTill = preferencesManager.getPrefByName(getApplicationContext(),
                Constants.PREF_UPDATING_TIME_TILL, "20:00");
        final Date updateTill = DateTimeUtils.calculateEndOfDay(timeTill);
        final PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0,
                updateStopIntent, 0);
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateTill.getTime(),
                BrelokPreferenceActivity.INTERVAL_DAY, pendingIntent);
        Log.i(BrelokPreferenceActivity.TAG,
                "Setted AlarmManager for UpdateStopReceiver will be started at "
                        + updateTill.toString());
    }
    
}
